import pandas as pd
import numpy as np
import itertools
import math as ma
import random

#飞机时刻表数据集与尾流安全距离数据集
Timetable = pd.read_csv("F:/plane_information/fzfinal.csv" , nrows = 36 , usecols = [0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ])   # 改nrows的个数为需要的飞机个数
Safety_distance = pd.read_csv("F:/plane_information/Safety_distance.csv" , nrows = 4 , usecols = [0 , 1 , 2])


class Plane(object):

    def __init__(self , plane_num):
        super(Plane , self).__init__()
        self.action_space = ["state"]   #改：动作值，有多少飞机就写进去几个动作，从1开始。
        for i in range(1 , plane_num + 1):
            self.action_space.append(i)
        self.n_actions = len(self.action_space)

    # 拿到最初的排序策略
    def start(self):
        list_plane = Timetable["plane_id"].tolist()
        return list_plane

    # 2.1.1 判断飞机是否可以向前移动
    def plane_change(self, action, observation):
        if action == 37:
            return True
        if observation.index(action) - 1 == -1:
            return False    #如果飞机是当前排序的第一架，则不能移动
        else:
            return True

    # 2.1.1 飞机是否可以向前移动,返回奖励值
    def get_reward(self, observation, action):
        sum_dtime = 0

        # 2.1.1.2 将顺序调换
        if action != 37:
            t_1 = observation.index(action) - 1
            t = observation.index(action)
            observation[t_1] , observation[t] = observation[t] , observation[t_1]
        # 2.1.13 按照动作顺序，计算Timetable中每架飞机的实际起飞时间 atd与dtime,etdp
        Timetable.loc[0:, 2:6] = 0

        list_plane = Timetable["plane_id"].tolist()
        for i in range(0, len(observation)):

            #准备：拿到当前的数据表

            lp = list_plane.index(observation[i])

            # 1.拿出来本次飞机的机场和未来位置
            outport = Timetable.loc[lp]["outport"]
            airport = Timetable.loc[lp]["airport"]

            # 2.拿到上一个机场该机场飞机的数据与上一个汇聚点飞机的数据
            lp_1 = -1
            lp_2 = -1
            for j in range(0, i):
                lp_index = list_plane.index(observation[j])
                if Timetable.loc[lp_index]["outport"] == outport:
                    lp_2 = lp_index  # 同港口的数据
                if Timetable.loc[lp_index]["airport"] == airport:
                    lp_1 = lp_index # 同机场的数据


            # 3.计算实际起飞时间atd
            if lp_1 == -1:
                Timetable.loc[lp , "atd"] = Timetable.loc[lp]["etd"] # 如果它是第一个则不需要取出来前一个飞机,实际起飞时间就是计划时间
            else:
                Timetable.loc[lp, "atd"] = Timetable.loc[lp_1]["atd"] + \
                                           Safety_distance.loc[int(Timetable.loc[lp_1]["Size"])][
                                               int(Timetable.loc[lp]["Size"])]
            # 4.计算实际离港时间atdp
            if lp_2 == -1:
                Timetable.loc[lp , "atdp"] = Timetable.loc[lp]["atd"] + 2
                Timetable.loc[lp, "safe"] = 0
            else:
                Timetable.loc[lp, "safe"] = Timetable.loc[lp_2]["atdp"] + \
                                            Safety_distance.loc[int(Timetable.loc[lp_2]["Size"])][
                                                int(Timetable.loc[lp]["Size"])] - 2


            # 5.防止提前起飞
            #if Timetable.loc[lp]["atd"] < Timetable.loc[lp]["etd"]:
            #    Timetable.loc[lp, "atd"] = Timetable.loc[lp]["etd"]
            #if Timetable.loc[lp]["atdp"] < Timetable.loc[lp]["etdp"]:
            #    Timetable.loc[lp, "atdp"] = Timetable.loc[lp]["etdp"]


            # 6.使用地面延误策略，尽可能在地上等待
            #if Timetable.loc[lp]["atdp"] - 2 > Timetable.loc[lp]["atd"]:
            #    Timetable.loc[lp, "atd"] = Timetable.loc[lp]["atdp"] - 2
            #else:
            #    Timetable.loc[i, "atdp"] = Timetable.loc[i]["atd"] + 2

            Timetable.loc[lp , "atd"] = max(Timetable.loc[lp]["etd"], Timetable.loc[lp]["atd"], Timetable.loc[lp]["safe"])
            Timetable.loc[lp , "atdp"] = Timetable.loc[lp , "atd"] + 2

            # 7.计算延误时间
            Timetable.loc[lp , "dtime"] = Timetable.loc[lp]["atd"] - Timetable.loc[lp]["etd"]

            sum_dtime += Timetable.loc[lp]["dtime"]

        return sum_dtime


    #计算FCFS下的延误时间
    def Record(self , n , it_n):
        record = []
        sum = 0
        ip = []
        dtime_sum = []
        #计算所有的延误时间
        for i in range(0 , n):

            #1.找到前一个机场的离开时间与前一个汇聚点的离开时间
            lp_1 = -1
            lp_2 = -1
            airport = Timetable.loc[i]["airport"]
            outport = Timetable.loc[i]["outport"]

            for j in range(0, i):
                if Timetable.loc[j]["airport"] == airport:
                    lp_1 = j
                if Timetable.loc[j]["outport"] == outport:
                    lp_2 = j

            # 计算实际起飞时间atd
            if lp_1 == -1:
                Timetable.loc[i , "atd"] = Timetable.loc[i , "etd"]
            else:
                Timetable.loc[i, "atd"] = Timetable.loc[lp_1, "atd"] + \
                                          Safety_distance.loc[int(Timetable.loc[lp_1]["Size"])][
                                              int(Timetable.loc[i]["Size"])]

            # 计算实际到达港口的时间 atdp = 实际起飞时间 + dis_time
            # 航班允许从机场起飞的时间：safe = 上一个汇聚点航班的离港时间 + sd - distime
            if lp_2 == -1:
                Timetable.loc[i , "atdp"] = Timetable.loc[i , "atd"] + 2
            else:
                Timetable.loc[i , "safe"] = Timetable.loc[lp_2, "atdp"] + \
                                           Safety_distance.loc[int(Timetable.loc[lp_2]["Size"])][
                                               int(Timetable.loc[i]["Size"])] - 2

            # 防止提前起飞
            #if Timetable.loc[i]["atd"] < Timetable.loc[i]["etd"]:
            #    Timetable.loc[i , "atd"] = Timetable.loc[i]["etd"]
            #if Timetable.loc[i]["atdp"] < Timetable.loc[i]["etdp"]:
            #    Timetable.loc[i , "atdp"] = Timetable.loc[i]["etdp"]

            #使用地面延误策略，尽可能在地上等待
            #if Timetable.loc[i]["atdp"] - 2 > Timetable.loc[i]["atd"]:
                #Timetable.loc[i , "atd"] = Timetable.loc[i]["atdp"] - 2
            #else:
                #Timetable.loc[i , "atdp"] = Timetable.loc[i]["atd"] + 2

            Timetable.loc[i , "atd"] = max(Timetable.loc[i]["etd"], Timetable.loc[i]["atd"], Timetable.loc[i]["safe"])
            Timetable.loc[i , "atdp"] = Timetable.loc[i , "atd"] + 2
            #计算dtime
            Timetable.loc[i , "dtime"] = Timetable.loc[i , "atd"] - Timetable.loc[i , "etd"]
            sum += Timetable.loc[i , "dtime"]
            ip.append(Timetable.loc[i]["plane_id"])

        #将排好序的飞机编号与单架飞机延误时间取出
        id = Timetable["plane_id"].tolist()
        record = Timetable["dtime"].tolist()
        print(Timetable)
        #计算总延误时间
        print("延误总时间：" , sum)
        print("飞机离港顺序：" , ip)
        print("飞机延误时间：" , record)

        # 将延误时间导入到图记录列表中
        line_record = [sum for i in range(int(it_n))]
        return line_record , record , sum

